<?php
/**
 * Ly - 插件函数库
 *
 * 插件实现功能函数
 *
 * Copyright (c) 2013 YinHailin All rights reserved.
 * @Author: YinHailin
 * @Authorize: Boren Network
 * @Created by YinHailin at 2013-11-01
 */

defined('LY_VERSION') or exit();

/**
 * 插件注册
 * 遍历插件库，注册所有插件，注册后的插件可安装/卸载
 */
function plugin_register() {
  //清空插件缓存
  if (is_dir(ROOT_PATH.'Runtime/Plugin/Cache/')) {
    dir_delete(ROOT_PATH.'Runtime/Plugin/Cache/');
  }
  $pluginList = F('Plugin.conf', '', CONF_PATH);  //读取插件列表
  $handle = opendir(PLUGIN_PATH);
  while(($file = readdir($handle)) !== false) {
    if (is_dir(PLUGIN_PATH.$file) && $file !== '.' && $file != '..') {
      if (file_exists(PLUGIN_PATH.$file.'/'.$file.'.php')) {
        //获取插件信息
        $content = file_get_contents(PLUGIN_PATH.$file.'/'.$file.'.php');
        //获取插件名称
        preg_match('/\$Name:([^\$]+)\$/', $content, $name);
        $plugin['name'] = trim($name[1]);
        //获取插件标识符
        $plugin['identifier'] = parse_name(trim($file));
        //获取插件类型
        preg_match('/\$Type:([^\$]+)\$/', $content, $type);
        $plugin['type'] = trim($type[1]);
        //获取插件作者
        preg_match('/\$Authors:([^\$]+)\$/', $content, $author);
        $plugin['author'] = trim($author[1]);
        //获取插件版本
        preg_match('/\$Versions:([^\$]+)\$/', $content, $versions);
        $plugin['versions'] = trim($versions[1]);
        //获取插件描述
        preg_match('/\$Description:([^\$]+)\$/', $content, $description);
        $plugin['description'] = trim($description[1]);
        //检查插件类型
        switch ($plugin['type']) {
          case 1 :
            $type='core';
            break;
          case 2 :
            $type = 'basic';
            break;
          case 3 :
            $type = 'extend';
            break;
          default :
            continue;
        }
        //插件注册
        $identifier = $plugin['identifier'];
        if (array_key_exists($identifier, $pluginList[$type])) {
          $newList[$type][$identifier] = $plugin;
          $newList[$type][$identifier]['install_status'] = $pluginList[$type][$identifier]['install_status'];
          if ($pluginList[$type][$identifier]['install_status']) {
            $pluginName = parse_name($plugin['identifier'], 1);
            include PLUGIN_PATH.$pluginName.'/'.$pluginName.'.php';
          }
        } else {
          $newList[$type][$identifier] = $plugin;
          $newList[$type][$identifier]['install_status'] = 0;
        }
      }
    }
  }
  closedir($handle);
  F('Plugin.conf', $newList, CONF_PATH, false);  //刷新插件列表
}

/**
 * 获取插件列表
 * 插件列表分为两类，第一类为已注册插件，第二类为未注册插件
 * 结构如：array(1=>'....', 2=>'....')
 * @param string $type 插件类型
 * @return array | false
 */
function plugin_list($type) {
  $pluginList = F('Plugin.conf', '', CONF_PATH);  //获取插件列表
  $newList = array();
  foreach ($pluginList[$type] as $value) {
    if ($value['install_status']) {
      $newList[1][] = $value;
    } else {
      $newList[2][] = $value;
    }
  }
  return $newList;
}

/**
 * 获取插件安装状态
 * @param string $identifier 插件标识符
 * @return boolean
 */
function plugin_status($identifier) {
  $identifier = parse_name($identifier);
  $plugin1 = plugin_list('core');
  $plugin2 = plugin_list('basic');
  $plugin3 = plugin_list('extend');
  $plugin = array();
  if (isset($plugin1[1])) { $plugin =  array_merge($plugin, $plugin1[1]);}
  if (isset($plugin2[1])) { $plugin =  array_merge($plugin, $plugin2[1]);}
  if (isset($plugin3[1])) { $plugin =  array_merge($plugin, $plugin3[1]);}
  if (two_array_search($plugin, $identifier) !== false) {
    return true;
  } else {
    return false;
  }
}

/**
 * 安装插件
 * @param string $type 插件类型
 * @param string $identifier 插件标识符
 * @return boolean
 */
function plugin_install($type, $identifier) {
  $pluginList = F('Plugin.conf', '', CONF_PATH);
  if (array_key_exists($identifier, $pluginList[$type])) {
    $file = parse_name($pluginList[$type][$identifier]['identifier'], 1);
    if (file_exists(PLUGIN_PATH.$file.'/Install.php')) {
      include PLUGIN_PATH.$file.'/Install.php';
    }
    $pluginList[$type][$identifier]['install_status'] = 1;
  } else {
    return false;
  }
  F('Plugin.conf', $pluginList, CONF_PATH, false);
  return true;
}

/**
 * 卸载插件
 * @param string $type 插件类型
 * @param string $identifier 插件标识符
 * @return boolean
 */
function plugin_uninstall($type, $identifier) {
  $pluginList = F('Plugin.conf', '', CONF_PATH);
  if (array_key_exists($identifier, $pluginList[$type])) {
    $file = parse_name($pluginList[$type][$identifier]['identifier'], 1);
    if (file_exists(PLUGIN_PATH.$file.'/Uninstall.php')) {
      include PLUGIN_PATH.$file.'/Uninstall.php';
    }
    $pluginList[$type][$identifier]['install_status'] = 0;
  } else {
    return false;
  }
  F('Plugin.conf', $pluginList, CONF_PATH, false);
  return true;
}

/**
 * 插件接口
 * 用于被插件调用，向插槽输送存储数据资源
 * @param string $func 调用的功能项
 * @param string $key 资源键值
 * @param array $data 相关数据
 * @return boolean
 */
function plugin($func, $key, $data) {
  if (strpos($func, '_') === false) { return false;}
  preg_match('/_([a-z]+)$/', $func, $match);
  $type = array_pop($match);
  $identifier = substr($func, 0, 0-strlen($type)-1);
  //资源存储
  switch ($type) {
    case 'file' :
      $result = plugin_file($identifier, $key, $data);
      break;
    case 'func' :
      $result = plugin_func($identifier, $key, $data);
      break;
    case 'info' :
      $result = plugin_info($identifier, $key, $data);
      break;
    case 'other' :
      $result = plugin_other($identifier, $key, $data);
      break;
  }
  return $result;
}

/**
 * 插槽接口
 * 用于被插槽调用，接受插件输送的数据
 * @param string $func 调用的功能项
 * @param string $key 资源键值
 * @param array $data 相关数据
 * @return mixed
 */
function rabbet($func, $key, $data=array()) {
  if (strpos($func, '_') === false) { return false;}
  preg_match('/_([a-z]+)$/', $func, $match);
  $type = array_pop($match);
  $identifier = substr($func, 0, 0-strlen($type)-1);
  //资源调用
  switch ($type) {
    case 'file' :
      return plugin_file($identifier, $key);
      break;
    case 'func' :
      $source = plugin_func($identifier, $key);
      $result = null;
      foreach ($source as $plu) {
        $class = A(parse_name($plu['plugin'], 1).'#//'.parse_name($plu['plugin'], 1));
        if (method_exists($class, $plu['method'])) {
          $return = call_user_func_array(array($class, $plu['method']), array($key, $data));
        }
        if ($result == '' || !is_array($return)) {
          $result = $return;
        } else {
          $result = array_merge($result, $return);
        }
      }
      return $result;
      break;
    case 'info' :
      return plugin_info($identifier, $key);
      break;
    case 'other' :
      return plugin_other($identifier, $key);
      break;
    default :
      return false;
  }
}

/**
 * 插件 - 文件类资源存取
 * 用于存储或读取插件中的文件类资源，约定该函数不被外部直接调用
 * @param string $identifier 标识符
 * @param string $key 资源键值
 * @param array $data 相关数据
 * @return mixed
 */
function plugin_file($identifier, $key, $data=array()) {
  $identifier = md5($identifier);
  $key = md5($key);
  $dataList = F(md5('plugin_file'), '', ROOT_PATH.'Runtime/Plugin/Cache/');
  if (!is_array($dataList)) { $dataList = array();}
  if (!empty($data)) {
    //判断对应的标识符是否已经存在，不存在则表示所存储的资源还不存在，可直接存储
    if (array_key_exists($identifier, $dataList)) {
      //判断对应的资源键值是否已经存在，不存在则表示所存储的资源还不存在，可直接存储
      if (array_key_exists($key, $dataList[$identifier])) {
        //判断资源是否已经存在，若存在，则无需再存储
        if (array_search($data, $dataList[$identifier][$key])) {
          array_push($dataList[$identifier][$key], $data);
        }
      } else {
        $dataList[$identifier][$key][] = $data;
      }
    } else {
      $dataList[$identifier][$key][] = $data;
    };
    return F(md5('plugin_file'), $dataList, ROOT_PATH.'Runtime/Plugin/Cache/');
  } else {
    if (array_key_exists($identifier, $dataList) && array_key_exists($key, $dataList[$identifier])) {
      return $dataList[$identifier][$key];
    } else {
      return '';
    }
  }
  return true;
}

/**
 * 插件 - 程序类资源存取
 * 用于存储或读取插件中的文件类资源，约定该函数不被外部直接调用
 * @param string $identifier 标识符
 * @param string $key 资源键值
 * @param array $data 相关数据
 * @return mixed
 */
function plugin_func($identifier, $key, $data=array()) {
  $identifier = md5($identifier);
  $key = md5($key);
  $dataList = F(md5('plugin_func'), '', ROOT_PATH.'Runtime/Plugin/Cache/');
  if (!is_array($dataList)) { $dataList = array();}
  if (!empty($data)) {
    //判断对应的标识符是否已经存在，不存在则表示所存储的资源还不存在，可直接存储
    if (array_key_exists($identifier, $dataList)) {
      //判断对应的资源键值是否已经存在，不存在则表示所存储的资源还不存在，可直接存储
      if (array_key_exists($key, $dataList[$identifier])) {
        //判断资源是否已经存在，若存在，则无需再存储
        if (array_search($data, $dataList[$identifier][$key])) {
          $dataList[$identifier][$key] = array_merge($dataList[$identifier][$key], array($data));
        }
      } else {
        $dataList[$identifier][$key][] = $data;
      }
    } else {
      $dataList[$identifier][$key][] = $data;
    };
    return F(md5('plugin_func'), $dataList, ROOT_PATH.'Runtime/Plugin/Cache/');
  } else {
    if (array_key_exists($identifier, $dataList) && array_key_exists($key, $dataList[$identifier])) {
      return $dataList[$identifier][$key];
    } else {
      return '';
    }
  }
  return true;
}

/**
 * 插件 - 信息类资源存取
 * 用于存储或读取插件中的文件类资源，约定该函数不被外部直接调用
 * @param string $identifier 标识符
 * @param string $key 资源键值
 * @param string | array $data 相关数据
 * @return mixed
 */
function plugin_info($identifier, $key, $data='') {
  $identifier = md5($identifier);
  $key = md5($key);
  $dataList = F(md5('plugin_info'), '', ROOT_PATH.'Runtime/Plugin/Cache/');
  if (!is_array($dataList)) { $dataList = array();}
  if (!empty($data)) {
    //判断该键是否存在对应的列表中，不存在则加入
    if (is_array($dataList[$identifier][$key])) {
      if (is_array($data)) {
        $dataList[$identifier][$key] = array_merge_recursive($dataList[$identifier][$key], $data);
      } else {
        $dataList[$identifier][$key][] = $data;
      }
    } else {
      if (is_array($data)) {
        $dataList[$identifier][$key] = $data;
      } else {
        $dataList[$identifier][$key][] = $data;
      }
    };
    F(md5('plugin_info'), $dataList, ROOT_PATH.'Runtime/Plugin/Cache/');
  } else {
    if (array_key_exists($identifier, $dataList) && array_key_exists($key, $dataList[$identifier])) {
      return $dataList[$identifier][$key];
    } else {
      return '';
    }
  }
  return true;
}

/**
 * 插件 - 其它类资源存取
+ 用于存储或读取插件中的文件类资源，约定该函数不被外部直接调用
 * @param string $identifier 标识符
 * @param string $key 资源键值
 * @param array $data 相关数据
 * @return mixed
 */
function plugin_other($identifier, $key, $data=array()) {
  $identifier = md5($identifier);
  $key = md5($key);
  $dataList = F(md5('plugin_other'), '', ROOT_PATH.'Runtime/Plugin/Cache/');
  if (!is_array($dataList)) { $dataList = array();}
  if (!empty($data)) {
    //判断对应的标识符是否已经存在，不存在则表示所存储的资源还不存在，可直接存储
    if (array_key_exists($identifier, $dataList)) {
      //判断对应的资源键值是否已经存在，不存在则表示所存储的资源还不存在，可直接存储
      if (array_key_exists($key, $dataList[$identifier])) {
        $dataList[$identifier][$key] = array_merge_recursive($dataList[$identifier][$key], $data);
      } else {
        $dataList[$identifier][$key] = $data;
      }
    } else {
      $dataList[$identifier][$key] = $data;
    };
    F(md5('plugin_other'), $dataList, ROOT_PATH.'Runtime/Plugin/Cache/');
  } else {
    if (array_key_exists($identifier, $dataList) && array_key_exists($key, $dataList[$identifier])) {
      return $dataList[$identifier][$key];
    } else {
      return '';
    }
  }
}

/**
 * 插件 - 执行SQL命令
 * 一般用于插件中的数据表创建、删除等处
 * @param string $sql SQL语句
 * @return boolean
 */
function plugin_excute($sql) {
  $obj = new MergeCore();
  $sql = str_replace("\r", "\n", $sql);
  $ret = array();
  $num = 0;
  foreach(explode(";\n", trim($sql)) as $query) {
    $ret[$num] = '';
    $queries = explode("\n", trim($query));
    foreach($queries as $query) {
      $ret[$num] .= (isset($query[0]) && $query[0] == '#') || (isset($query[1]) && isset($query[1]) && $query[0].$query[1] == '--') ? '' : $query;
    }
    $num++;
  }
  unset($sql);

  foreach($ret as $query) {
    $query = trim($query);
    if($query) {
      $result = $obj->Execute($query);
      if ($result === false) {
        $finish = false;
      }
    }
  }
  if ($finish === false) {
    return false;
  } else {
    return true;
  }
}